import os
import subprocess
from flask import Flask, request, render_template, send_from_directory, jsonify
from werkzeug.utils import secure_filename

app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
CONVERTED_FOLDER = 'converted'
ALLOWED_EXTENSIONS = {'ipynb'}

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['CONVERTED_FOLDER'] = CONVERTED_FOLDER

if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)
if not os.path.exists(CONVERTED_FOLDER):
    os.makedirs(CONVERTED_FOLDER)

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(filepath)

        # Convert to PDF
        try:
            output_filename = os.path.splitext(filename)[0]
            subprocess.run(
                ['jupyter', 'nbconvert', '--to', 'pdf', filepath, '--output-dir', app.config['CONVERTED_FOLDER'], '--output', output_filename],
                check=True,
                timeout=60  # Add a timeout for safety
            )
            pdf_filename = f"{output_filename}.pdf"
            return jsonify({'download_url': f'/converted/{pdf_filename}'})
        except subprocess.CalledProcessError as e:
            return jsonify({'error': f'Conversion failed: {e}'}), 500
        except subprocess.TimeoutExpired:
            return jsonify({'error': 'Conversion timed out'}), 500
        except Exception as e:
            return jsonify({'error': f'An unexpected error occurred: {e}'}), 500
    else:
        return jsonify({'error': 'Invalid file type. Please upload a .ipynb file.'}), 400

@app.route('/converted/<filename>')
def converted_file(filename):
    return send_from_directory(app.config['CONVERTED_FOLDER'], filename)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
